#include "imageviewer.h"
#include "callbacks.cxx"


// GLOBAL IMAGE AND WINDOW
Image myImage;
MyWindow *win = new MyWindow(0,0, "Image");
Fl_Box statusBoxX(0,378,35,30); // X status output mouse
Fl_Box statusBoxY(35,378,25,30);// Y status output mouse
Fl_Box statusBoxR(140,378,20,30); // Red under mouse status output
Fl_Box statusBoxG(160,378,20,30); // green under mouse
Fl_Box statusBoxB(180,378,20,30); // blue under mouse

std::list<undoCtr> undos; //keeps list of all modifications
std::list<undoCtr>::iterator undoPos = undos.begin(); //keeps the position in the list of undos

pixelInt leftMouseInt;//sets up left mouse click color holder INT
pixelUC leftMouseUC;//sets up left mouse click color holder unsigned Char

pixelInt rightMouseInt;//sets up right mouse click color holder INT
pixelUC rightMouseUC;//sets up right mouse click color holder Unsigned char

int tool = 0; // creates a global that is the holder of the current tool, default set to selection tool...

int eventhdlGBL = 0; // made this into a functking event handler copy so I can work with window events else where outside
						// of the functking event handler!!!


// Sorry got dumbfound for a few minutes... listening to zappa...
// gets the color from the picture at the current point where the mouse is... sets it to the leftMouseInt and UC
void getColorLeft();

// does the same as the other getColorLeft, just with the right click thing
void getColorRight();

// drawTool() does the drawing stuff (only pencil style)
void drawTool(); // tool 1

// lineTool() draws a line
void lineTool(); // tool 3

// getColorTool() its going to be addable to anywhere, but should be used in the event handling shit...
// I think this will be the standard for handling the tools in general...
// its fairly graceful
// call it
// it does all the work and thinking...
// thinking of standards 0 is selection 1 is draw 2 is color picker....
// just pop it where it should be ran it does the work of button detection and everything!
void getColorTool(); // tool 2

void replaceColorTool();// tool 4 left click is the color to replace with
// right click is used to select the color to replace

void replaceColor();// the actual method for matching and replacing the colors will be essentially
//a copy of the imageMod method just it does a few more things...

// toHex() converts the number (as a which is size (digits)
void toHex();

// toDec();
void toDec();

bool drawToolOn = 0; // default has the draw tool on , will probably add a general tool/edit enable disable
int	toolSize = 1; // holds the draw tool size, actual size is 2x the value held...

char xCoord[4], yCoord[4];
char rColor[4], gColor[4],bColor[4];


int MyWindow::handle(int event)
{
			eventhdlGBL = event;
			switch(event) //switch events
        {
        case FL_MOVE: // detects mouse move event
                getMouse(&mouseClick);// passes the window mouse point so it can be updated with relevant data
				std::cout << mouseClick.x << ", " << mouseClick.y << std::endl; // Diagnostic output
				toHex();
				std::cout << "r: " << (int)(myImage.getPixel(mouseClick.x, mouseClick.y, 0)) << " g: " << (int)(myImage.getPixel(mouseClick.x, mouseClick.y, 1)) << " b: " << (int)(myImage.getPixel(mouseClick.x, mouseClick.y, 2)) << std::endl;
				//xPosi = (char)mouseClick.x;
				
				gcvt(int(mouseClick.x), 3, xCoord);//Thanks Kevin this is very useful! takes the mouse click input and outputs it into a array
				gcvt(int(mouseClick.y), 3, yCoord);// does it for the y
				//gcvt((int)(myImage.getPixel(mouseClick.x, mouseClick.y, 0)),3,rColor);//does it for the r
				//gcvt((int)(myImage.getPixel(mouseClick.x, mouseClick.y, 1)),3,gColor);// does it for the g
				//gcvt((int)(myImage.getPixel(mouseClick.x, mouseClick.y, 2)),3,bColor);// does it for the b
				itoa((int)(myImage.getPixel(mouseClick.x, mouseClick.y, 0)),rColor,16);//does it for the r as hex
				itoa((int)(myImage.getPixel(mouseClick.x, mouseClick.y, 1)),gColor,16);// does it for the g as hex
				itoa((int)(myImage.getPixel(mouseClick.x, mouseClick.y, 2)),bColor,16);// does it for the b as hex
			
				toDec();
				//toHex(&gColor,3);
				//toHex(&bColor,3);

				statusBoxX.label(xCoord); // sets the labe to the array for x
				statusBoxY.label(yCoord); // set "" for y
				statusBoxR.label(rColor); // sets "" for r
				statusBoxG.label(gColor); // sets "" for g
				statusBoxB.label(bColor); // sets "" for b
                return 1;

        case FL_PUSH: // detect button push event
				getColorTool(); // this is a call to the get color tool it does all the work just pop it in the right section
				drawTool();
				lineTool();
				replaceColorTool();
                		

        case FL_DRAG:
				drawTool();
				lineTool();

        case FL_RELEASE:
				drawTool();
				lineTool();
                if(Fl::event_button()==1) //on right button release
                {

//                                scene.PickObjects(x, y, sizeX, sizeY);
//                                selectionRectangle = false;

                }


        case FL_FOCUS:
        case FL_UNFOCUS:
                this->redraw();
                return 1;
        default:
                return Fl_Window::handle(event);
        }

}

//gets the mouse x,y and passes it back in a relevant and correct form that can be used in tools
void MyWindow::getMouse(Point *mouse){
mouse->x = Fl::event_x();
mouse->y = Fl::event_y();
mouse->y = myImage.ny - mouse->y;
}





/* Following are the function definitions of the different image manipulation tools
   that are executed by the call back functions */

///*Kevin this is for you uncomment the start of this line... here is a basic rotational tool
// it almost works ha!
// go down to the end of Image::rotate() and uncomment the comment to comment out this section of code...

//Image::rotate function will rotate the image a specified number of degrees
void Image::rotate(double degrees) {
	std::cout << "Rotating by: " << degrees << std::endl;

/* So here is how it works kids...
// I need 4 cases to take into account for
// 0-90*
// 91-180*
// 181-270*
// 271-360* or 0
// these cases will determine what x min, x max, y min and y max are for the new buff size!
// cases of interest :
// x min = 0 * cos(degrees) + 0 * sin(degrees) top left 00
// y min = 0 * cos(degrees) - 0 * sin(degrees)
// x max = 0 * cos(degrees) + 0 * sin(degrees) top right 10
// y min = 0 * cos(degrees) - 0 * sin(degrees)
// x min = 0 * cos(degrees) + 0 * sin(degrees) bottom left 0-1 
// y min = 0 * cos(degrees) - 0 * sin(degrees)
// x max = 0 * cos(degrees) + 0 * sin(degrees) bottom right 1-1
// y min = 0 * cos(degrees) - 0 * sin(degrees)
// 306 + 252 for y
// 0 + 597 for x
*/

Image tempImage;
tempImage.rotation = degrees;

//so keep track of the max and mins of x and y

	// so logically the abs longest the image could be is l = sqrt(l^2 + w^2)

	// sets up the mins and maxes to be @ 0 for all
	int ymax=0;
	int ymin=0;
	int xmax=0;
	int xmin=0;

	// steps through all the pixels and finds the max and mins for x and y
	// Why? the max and min will ALWAYS be a corner, just do it 4 times //
	for(int x=0;x <= myImage.nx;x++){
		for(int y=0; y <= myImage.ny;y++){
			if(xmax < (x * cos(degrees)) + (y * sin(degrees))){
				xmax = (x * cos(degrees)) + (y * sin(degrees));
			}
			if(xmin > (x * cos(degrees)) + (y * sin(degrees))){
				xmin = (x * cos(degrees)) + (y * sin(degrees));
			}
			if(ymax < (y * cos(degrees)) - (x * sin(degrees))){
				ymax = (y * cos(degrees)) - (x * sin(degrees));
			}
			if(ymin > (y * cos(degrees)) - (x * sin(degrees))){
				ymin = (y * cos(degrees)) - (x * sin(degrees));
			}
		}
	}

	tempImage.nx = abs(xmin)+abs(xmax);//sets the x dim
	tempImage.ny = abs(ymin)+abs(ymax);//sets the y dim
	tempImage.ncolorChannels = myImage.ncolorChannels;//sets the color depth
	tempImage.data = new unsigned char [tempImage.nx*tempImage.ny*tempImage.ncolorChannels];//creates the new space

	// sets all the pixels in the temp space to the rotated image, null space is gray
	for(int x=0;x <= myImage.nx;x++){
		for(int y=0; y <= myImage.ny;y++){
			tempImage.setPixel(((x * cos(degrees)) + (y * sin(degrees))),((y * cos(degrees)) - (x * sin(degrees)))+abs(ymin),0,myImage.getPixel(x,y,0));
			tempImage.setPixel(((x * cos(degrees)) + (y * sin(degrees))),((y * cos(degrees)) - (x * sin(degrees)))+abs(ymin),1,myImage.getPixel(x,y,1));
			tempImage.setPixel(((x * cos(degrees)) + (y * sin(degrees))),((y * cos(degrees)) - (x * sin(degrees)))+abs(ymin),2,myImage.getPixel(x,y,2));
		}
	}
	//assignes the current image myImage to tempImage.
	myImage = tempImage;

	std::cout << "Rotation Finished..." << std::endl;
	std::cout << "xmin = " << xmin << std::endl;
	std::cout << "ymin = " << ymin << std::endl;
	std::cout << "xmax = " << xmax << std::endl;
	std::cout << "ymax = " << ymax << std::endl;
	std::cout << "x = " << myImage.nx << std::endl;
	std::cout << "y = " << myImage.ny << std::endl;

	
	win->resize(20,20,myImage.nx,myImage.ny);
	win->draw();
}
//*/

//Image::getPixel takes x y and ith color outputs color as a unsigned char
unsigned char Image::getPixel(int x, int y, int i) {
	unsigned char pixel=0;
	if(y <= ny +1){
		if(y >= 0){
			pixel = data[3*((ny-y)*nx)+(x*3)+i];
		}
	}
	return pixel;
}

//Image::setPixel takes x y and ith color and a int color value 0-255 sets the ith to the value
// So this has a bug when writting into the memory... suprise, or its in something in the heap struct...
// it only occurs when you draw on the upper ny bound of the picture....
// it proceeds to draw into the heap memory area....
// FML --wcars05
void Image::setPixel(int x, int y, int i, int value) {
	unsigned char pixel = getPixel(x,y,i);
	(int)pixel;
	if(y < ny+1){
		if(y >= 0){
			if(x < nx){
				if(x >= 0){
					data[3*((ny-y)*nx)+(x*3)+i] = value;
				}
			}
		}
	}
}
//Image::zoom() performs a 2X zoom on the image
void Image::zoom() {
	
	Image newImage;
	//newImage.data = new unsigned char[2*nx*ny*ncolorChannels];
    int j = 0;
	int k = 0;
	/*
  for(int y=0; y<=myImage.ny; y++)
 {
	for(int x=0; x<myImage.nx; x++)
	{
		for(int i=0; i<3; ++i){
			newImage.setPixel(j,k,i,myImage.getPixel(x,y,i));
			newImage.setPixel(j+1,k,i,myImage.getPixel(x,y,i));
			newImage.setPixel(j,k+1,i,myImage.getPixel(x,y,i));
			newImage.setPixel(j+1,k+1,i,myImage.getPixel(x,y,i));

		}
		j++;
	}
	k++;
 }*/
	myImage = newImage;
	win->resize(300,200,nx,ny);
	win->show();
	win->draw();
	
}
//Image::modPixel takes x,y and ith color and then the value as an int that needs to be added to
// the ith color
void Image::modPixel(int x, int y, int i, int value) {
	unsigned char pixel = getPixel(x,y,i);
	(int)pixel;
	if (pixel > 1 || pixel < 255)
		data[3*(y*nx)+(x*3)+i] += value;
}

//Image::modImage updates the image by adding what ever value is passed to it for each channel (this is applied to the whole image!)
void Image::modImage(int r,int g,int b){
	for(int y=0; y<ny; y++) {
                        for(int x=0; x<nx; x++) {

								int cr=0;//intializes current red to 0
								int cg=0;//initiallizes current green to 0
								int cb=0;//initializes current blue to 0

								cr = myImage.getPixel(x,y,0);//gets the current pixelvalue red sets it to cr
								cg = myImage.getPixel(x,y,1);//gets the current pixelvalue green sets it to cg
								cb = myImage.getPixel(x,y,2);//gets the current pixelvalue blue sets it to cb

								int wr= cr + r; // intializes writered to current red + red adjust value
								int wg= cg + g;//initializes writegreen to current green + green adjust value
								int wb= cb + b; //initializes writeblue to current blue + blue adjust

								if(wr < 0){ // need red check for current pixel
									wr=0;//if r+cr < 0 then min's @0
								}
								if(wr > 255){
									wr=255;//checks if r+cr>255 then maxes @ 255
								}
								if(wg < 0){//need green check for current pixel
									wg=0;//if g+cg < 0 then min's @0
								}
								if(wg > 255){//checks if g+cg>255 then maxes @ 255
									wg=255;
								}
								if(wb < 0){//need blue check for current pixel
									wb=0;//if b+cb < 0 then min's @0
								}
								if(wb > 255){//checks if b+cb>255 then maxes @ 255
									wb=255;
								}

                                myImage.setPixel(x,y,0,wr);
                                myImage.setPixel(x,y,1,wg);
                                myImage.setPixel(x,y,2,wb);
                        }
        }
	std::cout << "Image::modImage, " << "int r=" << r << "int g=" << g << "int b=" << b<< "IT should be updating the color values.... " << std::endl;
}

//Image::copyFromImage passed an object's pointer and then fills it with the current image... used for undoing stuff...
//MUST HAVE SAME SIZE OF DATA OTHER WISE SELF DESTRUCTS!!!
void Image::copyFromImage(unsigned char *image){
 int k=0;
  for(int j = ny * nx * ncolorChannels; j>0;j--)
	{
		image[k] = data[k];
		k++;
	}
}
//Image::copyToImage used to pass a set of data into the image your working with
//must have same size of data!!!!
void Image::copyToImage(unsigned char *image){
 int k=0;
  for(int j = ny * nx * ncolorChannels; j>0;j--)
	{
		data[k] = image[k];
		k++;
	}
}

void MyWindow::draw() {
	    // FLTK DRAW METHOD

	/** 
	* Draws data buffer on the window
	**/
	fl_draw_image((const uchar*)myImage.data, 0, 0, myImage.nx, myImage.ny, 3, myImage.nx*3);
	
	win->resizable();
}
void Image::redChannel() {
	//int avg;
	for(int y=0; y<ny; y++) {
			for(int x=0; x<nx; x++) {
				myImage.setPixel(x,y,1,0);
				myImage.setPixel(x,y,2,0);
			}
	}
	win->redraw();
}
void Image::greenChannel() {
	for(int y=0; y<ny; y++) {
			for(int x=0; x<nx; x++) {
				myImage.setPixel(x,y,0,0);
				myImage.setPixel(x,y,2,0);
			}
	}
	win->redraw();
}
void Image::blueChannel() {
	
	for(int y=0; y<ny; y++) {
			for(int x=0; x<nx; x++) {
				myImage.setPixel(x,y,0,0);
				myImage.setPixel(x,y,1,0);
			}
	}
	win->redraw();
}

//Image::brighten function increases the brightness of the image that is currently displayed
void Image::brighten() {
	for(int y=0; y<=ny; y++) {
			for(int x=0; x<=nx; x++) {
				for(int i=0; i<3; ++i) {
					if ( myImage.getPixel(x,y,i) > 245)
						myImage.setPixel(x,y,i,255);
					else
						myImage.modPixel(x,y,i, 10);
					}
			}
	}
	win->redraw();
}


//Image::darken function reduces the brightness of the image that is currently displayed
void Image::darken() {
	for(int y=0; y<ny; y++) {
			for(int x=0; x<nx; x++) {
				for(int i=0; i<3; ++i) {
					if ( myImage.getPixel(x,y,i) < 10)
						myImage.setPixel(x,y,i,0);
					else
						myImage.modPixel(x,y,i, -10);
					}
			}
	}
	win->redraw();
}

//Image::posterize function adds a posterization effect to the image that iscurrently displayed
void Image::posterize() {
	unsigned char color;
	for(int y=0; y<ny; y++) {
			for(int x=0; x<nx; x++) {
				for(int i=0; i<3; ++i) {
					color = myImage.getPixel(x,y,i);
					if ( color > 128)
						if (color + 10 > 255)
							myImage.setPixel(x,y,i,255);
						else
							myImage.modPixel(x,y,i,10);
					else
						if (color - 10 < 0)
							myImage.setPixel(x,y,i,0);
						else
							myImage.modPixel(x,y,i,-10);
					}
			}
	}
	win->redraw();
}
//Image::mirrorX function flips the image along the x-axis
void Image::mirrorX() {
	
	unsigned char temp;
	for(int y=0; y<ny; ++y) {
			for(int x=0; x<=nx/2; x++) {
				for(int i=0; i<3; ++i) {
					temp = myImage.getPixel(x,y,i);
					myImage.setPixel(x,y,i,myImage.getPixel(nx-x-1,y,i));
					myImage.setPixel(nx-x-1, y, i, temp);
				}
			}
		 }
	win->redraw();
}

//Image::mirrorY function flips the image along the y-axis
void Image::mirrorY() {
	
	unsigned char temp;
	for(int y=0; y<=ny/2-1; ++y) {
			for(int x=0; x<=nx; x++) {
				for(int i=0; i<3; ++i) {
					temp = myImage.getPixel(x,y,i);
					myImage.setPixel(x,y,i,myImage.getPixel(x,ny-y-1,i));
					myImage.setPixel(x, ny-y-1, i, temp);
				}
			}
		 }
	win->redraw();
}

//Image::grayscale function shows the image in gray scale
void Image::grayscale() {
	int avg;
	for(int y=0; y<ny; y++) {
			for(int x=0; x<nx; x++) {
				avg = ((int)myImage.getPixel(x,y,0) + (int)myImage.getPixel(x,y,1) + (int)myImage.getPixel(x,y,2))/3;
				myImage.setPixel(x,y,0,avg);
				myImage.setPixel(x,y,1,avg);
				myImage.setPixel(x,y,2,avg);
			}
	}
	win->redraw();
}

//Image::get_file_type finds out the file type via the extension
int Image::get_file_type(std::string filename){

	//enum extension{ppm=1,jpg=2,jpeg=3,gif=4,png=5,bmp=6};
	//extension ext;
	int result = 0;
	std::string ext = "";
	ext = filename.substr(filename.find_last_of(".")+ 1);
	std::cout << "File extension is: " << ext << std::endl;

	if(ext == "ppm" || ext == "pgm")
		result = 1;
	else if(ext == "jpg" || ext == "jpeg")
		result = 2;
	else if(ext == "gif")
		result = 3;
	else if(ext == "png")
		result = 4;
	else if(ext == "bmp")
		result = 5;	

	return result;
}

/**************************************************************************************
Image::ReadFile function is called when the "Open" menu item is chosen.
This function opens a file chooser window and based on the file type (.ppm,.jpg,etc.).
It then calls the correct function to read that file type and displays the image.
***************************************************************************************/
void Image::ReadFile() // Just a note this seems to be broken, it could be just me - wcars05 
{
 fl_register_images();
 //open the fluid file chooser and choose a file to open
 char *file = fl_file_chooser("Pick a file to READ from","*.{pgm,ppm,vol,jpg,bmp,gif,png}","",1);
 

 //if file is empty then do nothing
 if(file == NULL){		                            
	 std::cout << "File is empty!!!!" << std::endl;  //user feedback... should make a message box pop up uses standard I/O for now
	 return;
 }
 
 

 //initialize data buffer to ensure no "garbage" in image
 if(n>0)                               
	myImage.flush_buffer();

 
 //fl_register_images();
 //switch statement here to determine which file type it is and call proper file open 
 //routine based on that file type... need to determine best way to examine file name
    std::string filename(file);		//temp variable so we don't corrupt the file pointer itself EVER!
	switch( get_file_type(filename) ){

	case 1: 
		this->Read_ppm(file);	//Case: file is a .ppm file
		break;

	case 2:
		this->Read_jpg(file);	//file is a .jpg or .jpeg file
		break;

	case 3:
		this->Read_gif(file);
		break;

	case 4:
		this->Read_png(file);
		break;

	case 5:
		this->Read_bmp(file);
		break;

	default:
		std::cout << "File type not supported!" << std::endl;
		std::cout << get_file_type(filename);
		break;

}

		win->show();
}

void Image::Read_ppm(char *file){   //called to read .ppm image files

 FILE *fp;
 fp=fopen(file, "rb");
 fgets(str,100,fp);
 sscanf(str,"%s",imageType);

 if(!strncmp(imageType,"P5",2))                  
	ncolorChannels=1;
else if(!strncmp(imageType,"P6",2))     
	ncolorChannels=3;

 fgets(str,100,fp);
 while(str[0]=='#')           
	 fgets(str,100,fp);

 sscanf(str,"%d %d",&nx,&ny);
 fgets(str,100,fp);
 n=nx*ny;
 unsigned char *tempdata = new unsigned char[n*ncolorChannels];
 data = new unsigned char [n*ncolorChannels];
 fread(data,sizeof(unsigned char),n*ncolorChannels,fp);
 size= nx*ny*ncolorChannels;


win->resize(20,20,nx,ny);
win->resizable(win);
 win->show();
 

 fclose(fp);
return;
}
 

void Image::Read_jpg(char *file){	//called to read .jpg image files
	
	//fl_register_images();
	//int h = file.h();
	//int w = file.w();
	win->resize(20,20,720,486);
	Fl_JPEG_Image *jpg = new Fl_JPEG_Image(file);
	win->image(jpg);
	win->resizable();
	win->draw();
	return;
}

void Image::Read_bmp(char *file){	//called to read .bmp image files

}

void Image::Read_gif(char *file){	//called to read .gif image files

}

void Image::Read_png(char *file){

}
// Image::flush_buffer() cleans up the MyImae.data and the undo buffer list...
void Image::flush_buffer(){			//function will be used to flush the file buffer in order to start fresh
delete data;
	while(!undos.empty()){	// well FML IDK why I can't get it working so I'll just force it on... //(undoPos-- != undos.end())&&(undoPos == undos.begin())
		undoPos = undos.end(); // gets end of the undo list
		if(!undos.empty()){
			// relocated the next line to fix the crashing issue... 
			undoPos--;// sets the iterator to the last items location
			delete undoPos->imageData;// this line is reserved for memory clean up... guessing delete or ~undoPos->imageData or something similar needs to be tested...
			undos.pop_back(); // removes the last item from the undo container
		}
	}
}

/*****************************************************************************************
Image::WriteFile is called when the "Save" menu item is chosen. 
This function opens a file chooser window and based on the file type (.ppm,.jpg,etc.).
It then calls the correct function to read that file type and saves the image to a file.
******************************************************************************************/
void Image::WriteFile() 
{
 char *file = fl_file_chooser("Pick a file to WRITE to","*.{pgm,ppm,vol,jpg,bmp,gif}", "");

 if(file == NULL)                              
	 return;
	 //switch statement here to determine which file type it is and call proper file write 
     //routine based on that file type... need to figure out how to write other files before 
	 //implementing the other switch arguments
	 //switch( imageType ){

	//case "ppm": 
		this->Write_ppm(file);	//Case: file is a .ppm file
/*		break;

	case "jpg":
		this->Read_jpg(file);
		break;

	case "bmp":
		this->Read_bmp(file);
		break;

	case "gif":
		this->Read_gif(file);
		break;
}*/

	
}

void Image::Write_ppm(char *file){

// outputs the header info into the file
unsigned char newImage = nx*ny*ncolorChannels;
std::ofstream out_ppm;  // Creates the file stream for output out_ppm
out_ppm.open(file, std::ofstream::binary);	// Opens out_ppm on file
 out_ppm << imageType;	// Outputs image type
 out_ppm << '\n';		// return line
 out_ppm << "# Created with ImageViewer" << '\n';	// Outputs created by comment w/newline
 out_ppm << nx << ' ' << ny << '\n' << "255" << "\n";	// Outputs picture dimmesions  w/newline

  
		for(int y=0; y<=ny; y++) {
			for(int x=0; x<nx; x++) {
				for(int i=0; i<3; ++i) {
					out_ppm << myImage.getPixel(x,y,i);
				}
			}
		 }
out_ppm.close(); // closes the file stream

}//end Image::Write_ppm()

void Image::Write_jpg(){

}

void Image::Write_bmp(){

}

void Image::Write_gif(){

}

void Image::Write_png(){

}

static void cb_New(Fl_Menu_*, void*) {
	std::cout << "New Callback";
	myImage.nx = 500;
	myImage.ny = 500;
	myImage.ncolorChannels = 3;
	myImage.n=myImage.nx*myImage.ny;
	myImage.data = new unsigned char [myImage.n*myImage.ncolorChannels];
	myImage.size= myImage.nx*myImage.ny*myImage.ncolorChannels;
	for(int k = 0; k<myImage.size;k++){
		myImage.data[k]=255;
	}
	win->resize(20,20,myImage.nx,myImage.ny);
	win->show(); 

}

static void cb_Close(Fl_Menu_*, void*) {
	win->hide();
	myImage.flush_buffer();
}
static void cb_Resize(Fl_Menu_*, void*) {
	win->resize(30,30, 300, 300);
	win->redraw();
}

//Menubar
Fl_Menu_Item menu_File[] = {
 {"File", FL_ALT+'f',  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"New", FL_COMMAND+'n',  (Fl_Callback*)cb_New, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Open", FL_COMMAND+'o',  (Fl_Callback*)cb_Open, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Save", FL_COMMAND+'s',  (Fl_Callback*)cb_Save, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Close", FL_COMMAND+'c',  (Fl_Callback*)cb_Close, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Exit", 0,  (Fl_Callback*)cb_Exit, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Edit", FL_ALT+'e',  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Undo", FL_COMMAND+'z',	(Fl_Callback*)cb_undo, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Mirror X", 0,  (Fl_Callback*)cb_MirrorX, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Mirror Y", 0,  (Fl_Callback*)cb_MirrorY, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Gray Scale", 0,  (Fl_Callback*)cb_Grayscale, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Rotate", 0, (Fl_Callback*)cb_Rotate, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Red Channel", 0,  (Fl_Callback*)cb_RedChannel, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Green Channel", 0,  (Fl_Callback*)cb_GreenChannel, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Blue Channel", 0,  (Fl_Callback*)cb_BlueChannel, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Brighten", 0,  (Fl_Callback*)cb_Brighten, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Darken", 0,  (Fl_Callback*)cb_Darken, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Posterize", 0,  (Fl_Callback*)cb_Posterize, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"View", FL_ALT+'v',  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Zoom x2", 0, (Fl_Callback*)cb_Zoom, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {"Redraw", 0, (Fl_Callback*)cb_Redraw, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Image", FL_ALT+'i',  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"Resize", 0, (Fl_Callback*)cb_Resize, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0},
 {"Help", FL_ALT+'h',  0, 0, 64, FL_NORMAL_LABEL, 0, 14, 0},
 {"About", 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
 {0,0,0,0,0,0,0,0,0}
};

//Enables draw on draw button click from toolbox
void cb_drawButton(Fl_Button*, void*) { 
	std::cout << "DrawToolOn pre " << drawToolOn << std::endl;
	tool = 1;//sets the tool to the draw tool
	drawToolOn = 1;
	win->cursor(Fl_Cursor::FL_CURSOR_CROSS);
	std::cout << "DrawToolOn post " << drawToolOn << std::endl;
}
void cb_getColorButton(Fl_Button*, void*){
	tool = 2;	// sets the tool to the color picker chooser thinger
				// it enables the tool otherwise
	win->cursor(Fl_Cursor::FL_CURSOR_HAND);
	std::cout << "Color picker selected" << std::endl;
}

void cb_lineButton(Fl_Button*, void*){
	tool = 3;	// sets the tool to the color picker chooser thinger
				// it enables the tool otherwise
	win->cursor(Fl_Cursor::FL_CURSOR_DEFAULT);
	drawToolOn = 1; // universal switch, apparently used to turn drawing tools on... go me...
	std::cout << "Line Tool selected" << std::endl;
}
void cb_replaceColor(Fl_Button*, void*){
	tool = 4;	// sets the tool to the color picker chooser thinger
				// it enables the tool otherwise
	win->cursor(Fl_Cursor::FL_CURSOR_CROSS);
	drawToolOn = 1; // universal switch, apparently used to turn drawing tools on... go me...
	std::cout << "Replace Color Tool selected" << std::endl;
}

static void cb_changeColorRed(Fl_Button* b, void*) {
	leftMouseInt.r = 255;
	leftMouseInt.g = 0;
	leftMouseInt.b = 0;
}
static void cb_changeColorGreen(Fl_Button* b, void*) {
	leftMouseInt.r = 0;
	leftMouseInt.g = 255;
	leftMouseInt.b = 0;
}
static void cb_changeColorYellow(Fl_Button* b, void*) {
	leftMouseInt.r = 255;
	leftMouseInt.g = 255;
	leftMouseInt.b = 0;
}
static void cb_changeColorBlue(Fl_Button* b, void*) {
	leftMouseInt.r = 0;
	leftMouseInt.g = 0;
	leftMouseInt.b = 255;
}
static void cb_changeColorPurple(Fl_Button* b, void*) {
	leftMouseInt.r = 255;
	leftMouseInt.g = 0;
	leftMouseInt.b = 255;
}
static void cb_changeColorCyan(Fl_Button* b, void*) {
	leftMouseInt.r = 0;
	leftMouseInt.g = 255;
	leftMouseInt.b = 255;
}
static void cb_changeColorWhite(Fl_Button* b, void*) {
	leftMouseInt.r = 255;
	leftMouseInt.g = 255;
	leftMouseInt.b = 255;
}
static void cb_changeColorBlack(Fl_Button* b, void*) {
	leftMouseInt.r = 0;
	leftMouseInt.g = 0;
	leftMouseInt.b = 0;
}

Fl_Menu_Bar *menubar=(Fl_Menu_Bar *)0;


int main(int argc, char**argv) {
	Fl::visual(FL_RGB);


     Fl_Double_Window* w;
  { Fl_Double_Window* o = new Fl_Double_Window(250, 400);
    w = o;
    { menubar = new Fl_Menu_Bar(0, 0, 250, 20);
    } // Fl_Menu_Bar* o
    { 
      menubar->menu(menu_File);
    } // Fl_Menu_Button* o

//Here is where I initiallize the left and right to white and black... I think...
//No initialization, defaults to black (Kevin)

leftMouseInt.r = 0;
leftMouseInt.g = 0;
leftMouseInt.b = 0;
leftMouseUC.r = unsigned char(0);
leftMouseUC.g = unsigned char(0);
leftMouseUC.b = unsigned char(0);
rightMouseInt.r = 255;
rightMouseInt.g = 255;
rightMouseInt.b = 255;
rightMouseUC.r = unsigned char(255);
rightMouseUC.g = unsigned char(255);
rightMouseUC.b = unsigned char(255);
// end initializing...*/
  
// Color chooser

	//Red color
	Fl_Button* redColor = new Fl_Button(205, 25, 20, 20);
      redColor->box(FL_BORDER_BOX);
      redColor->color((Fl_Color)1);
	  redColor->callback((Fl_Callback*)cb_changeColorRed);

   //Green color
	Fl_Button* greenColor = new Fl_Button(225, 25, 20, 20);
      greenColor->box(FL_BORDER_BOX);
      greenColor->color((Fl_Color)2);
	  greenColor->callback((Fl_Callback*)cb_changeColorGreen);

   // Yellow
	Fl_Button* yellowColor = new Fl_Button(205, 45, 20, 20);
      yellowColor->box(FL_BORDER_BOX);
      yellowColor->color((Fl_Color)3);
	  yellowColor->callback((Fl_Callback*)cb_changeColorYellow);

    //Blue
	Fl_Button* blueColor = new Fl_Button(225, 45, 20, 20);
	  blueColor->box(FL_BORDER_BOX);
      blueColor->color((Fl_Color)4);
	  blueColor->callback((Fl_Callback*)cb_changeColorBlue);

	//Purple
    Fl_Button* purpleColor = new Fl_Button(205, 65, 20, 20);
	  purpleColor->box(FL_BORDER_BOX);
      purpleColor->color((Fl_Color)5);
	  purpleColor->callback((Fl_Callback*)cb_changeColorPurple);

	//Cyan
	Fl_Button* cyanColor = new Fl_Button(225, 65, 20, 20);
	  cyanColor->box(FL_BORDER_BOX);
      cyanColor->color((Fl_Color)6);
	  cyanColor->callback((Fl_Callback*)cb_changeColorCyan);

	Fl_Button* whiteColor = new Fl_Button(205, 85, 20, 20);
	  whiteColor->box(FL_BORDER_BOX);
      whiteColor->color((Fl_Color)7);
	  whiteColor->callback((Fl_Callback*)cb_changeColorWhite);

	Fl_Button* blackColor = new Fl_Button(225, 85, 20, 20);
	  blackColor->box(FL_BORDER_BOX);
      blackColor->color((Fl_Color)8);
	  blackColor->callback((Fl_Callback*)cb_changeColorBlack);
	  //End Color chooser
// RED SLIDER
	Fl_Slider *sliderred = new Fl_Slider(10,280, 15, 100);
	sliderred->type(FL_VERT_NICE_SLIDER);
	sliderred->callback((Fl_Callback*)cb_SliderRed);
	sliderred->scrollvalue(0, 1, 0, 510);
	sliderred->color(FL_RED);
	sliderred->color2(FL_BLACK);
	sliderred->bounds(50,-50);
// END RED SLIDER
// Green SLIDER
	Fl_Slider *slidergreen = new Fl_Slider(40,280, 15, 100);
	slidergreen->type(FL_VERT_NICE_SLIDER);
	slidergreen->callback((Fl_Callback*)cb_SliderGreen);
	slidergreen->scrollvalue(0, 1, 0, 510);
	slidergreen->color(FL_GREEN);
	slidergreen->color2(FL_BLACK);
	slidergreen->bounds(50,-50);
// END Green SLIDER
// Blue SLIDER
	Fl_Slider *sliderblue = new Fl_Slider(70,280, 15, 100);
	sliderblue->type(FL_VERT_NICE_SLIDER);
	sliderblue->callback((Fl_Callback*)cb_SliderBlue);
	sliderblue->scrollvalue(0, 1, 0, 510);
	sliderblue->color(FL_BLUE);
	sliderblue->color2(FL_BLACK);
	sliderblue->bounds(50,-50);
// END Blue SLIDER
// Brightness Slider
	Fl_Slider *sliderbright = new Fl_Slider(0,260, 100, 15);
	sliderbright->type(FL_HOR_NICE_SLIDER);
	sliderbright->box(FL_BORDER_BOX);
	sliderbright->callback((Fl_Callback*)cb_Brighten);
	sliderbright->scrollvalue(0, 1, 0, 510);
	sliderbright->color(FL_WHITE);
	sliderbright->color2(FL_BLACK);
	sliderbright->bounds(-255,255);
	sliderbright->image(image_brightness);
	sliderbright->align(FL_ALIGN_RIGHT);
// END Brightness Slider
	/* Line width slider */

	Fl_Slider *lineToolSize = new Fl_Slider(10,180, 10, 50);
	lineToolSize->type(FL_VERT_NICE_SLIDER);
	lineToolSize->box(FL_BORDER_BOX);
	lineToolSize->callback((Fl_Callback*)cb_LineSize);
	lineToolSize->scrollvalue(1, 1, 1, 10);
	lineToolSize->color(FL_GRAY);
	lineToolSize->color2(FL_BLACK);
	lineToolSize->bounds(1,10);
	lineToolSize->image(image_linesize);
	lineToolSize->align(FL_ALIGN_RIGHT);

	/* End line width slider*/
	/* Drawing buttons */
	{ Fl_Button* o = new Fl_Button(0, 22, 64, 50, "Draw");
      o->image(image_pencil);
	  o->callback((Fl_Callback*)cb_drawButton); // for button call back
	  o->shortcut(FL_COMMAND+'d');
    } // Fl_Button* o Draw Button
    { Fl_Button* o = new Fl_Button(65, 22, 65, 50, "Zoom");
      o->image(image_zoom);
	  o->callback((Fl_Callback*)cb_Zoom);
    } // Fl_Button* o Zoom Button
    { Fl_Button* o = new Fl_Button(130, 22, 65, 50, "Mirror X");
      o->image(image_mirror);
	  o->callback((Fl_Callback*)cb_MirrorX);
    } // Fl_Button* o Mirror X button
    { Fl_Button* o = new Fl_Button(65, 72, 65, 50, "Rotate");
      o->image(image_rotate);
	  o->callback((Fl_Callback*)cb_Rotate);
    } // Fl_Button* o Rotate Button
    { Fl_Button* o = new Fl_Button(0, 72, 65, 50, "Eye Drop");
      o->image(image_eyedropper);
	  o->callback((Fl_Callback*)cb_getColorButton);
	} // Fl_Button* o Eyedropper
	{ Fl_Button* o = new Fl_Button(0, 122, 65, 50, "Line");
      o->image(image_line);
	  o->callback((Fl_Callback*)cb_lineButton);
	} // Fl_Button* o Line Tool
	{ Fl_Button* o = new Fl_Button(130, 72, 65, 50, "Mirror Y");
      o->image(image_mirrorY);
	  o->callback((Fl_Callback*)cb_MirrorY);
	} // Fl_Button* o Mirror Y
	{ Fl_Button* o = new Fl_Button(65, 122, 65, 50, "Grayscale");
      o->image(image_grayscale);
	  o->callback((Fl_Callback*)cb_Grayscale);
	} // Fl_Button* o Grayscale
	{ Fl_Button* o = new Fl_Button(130, 122, 65, 50, "Sub");
      //o->image(image_grayscale);
	  o->callback((Fl_Callback*)cb_replaceColor);
	} // Fl_Button* o replaceColor


	o->add(statusBoxX);//X coord adds these status boxes into the tool box
	o->add(statusBoxY);//Y Coord
	o->add(statusBoxR);// R
	o->add(statusBoxG);// G
	o->add(statusBoxB);// B
	o->end();
  } // Fl_Double_Window* o
  w->show(argc, argv);
  return Fl::run();
}


void undoAdd(){
	// undo stuff....
	undoCtr * imageUpdate = new undoCtr(); // makes an undo container item
	imageUpdate->y = myImage.ny; // sets the height
	imageUpdate->x = myImage.nx; // sets the width
	imageUpdate->rotation = myImage.rotation; // sets the rotation
	imageUpdate->imageData = new unsigned char[myImage.ncolorChannels*myImage.nx*myImage.ny]; // creates a array the same size as the image.data sets the data to point at it
	imageUpdate->channels = myImage.ncolorChannels; // sets the number of channels in the data
	myImage.copyFromImage(imageUpdate->imageData); // should probably make like a copy constructor or something
	undos.push_back(*imageUpdate); // adds the image into the container YEAH! ready for action!
	// end of undo block of stuff.....
}
void undoDel(){
	undoPos = undos.end(); // gets end of the undo list
	if(!undos.empty()){	// well FML IDK why I can't get it working so I'll just force it on... //(undoPos-- != undos.end())&&(undoPos == undos.begin())
		// relocated the next line to fix the crashing issue... 
		undoPos--;// sets the iterator to the last items location
		delete myImage.data; //cleans up the old image
		myImage.ny = undoPos->y; //sets the image to the previous for restoration hight
		myImage.nx = undoPos->x; //sets the image to the previous to the rest width
		myImage.rotation = undoPos->rotation; // does the rotation thinger ammount
		myImage.ncolorChannels = undoPos->channels; // thing for color channels
		myImage.data = new unsigned char [myImage.ny*myImage.nx*myImage.ncolorChannels];
		myImage.copyToImage(undoPos->imageData); //sends the pointer of the undo'list's data to the copy to image thinger
		delete undoPos->imageData;// this line is reserved for memory clean up... guessing delete or ~undoPos->imageData or something similar needs to be tested...
		undos.pop_back(); // removes the last item from the undo container
	}
	else{
		//std::cout << "Sorries, outs of the thingers you luk'n fur sir'" << std::endl;
	}
}
void getColorLeft(){
	win->getMouse(&win->mouseClick);//updates the mouse location
	leftMouseInt.r=(int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 0));//sets the r value for the int left click
	leftMouseInt.g=(int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 1));// "" green
	leftMouseInt.b=(int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 2));// "" blue
	leftMouseUC.r=myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 0);// "" char red
	leftMouseUC.g=myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 1);// "" char green
	leftMouseUC.b=myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 2);// "" char blue
}

void getColorRight(){
	win->getMouse(&win->mouseClick);//updates the mouse location
	rightMouseInt.r=(int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 0));//sets the r value for the int right click
	rightMouseInt.g=(int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 1));// "" green
	rightMouseInt.b=(int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 2));// "" blue
	rightMouseUC.r=myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 0);// "" for char red
	rightMouseUC.g=myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 1);// "" for char green
	rightMouseUC.b=myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 2);// "" for char blue
}

void drawTool(){
	if(tool == 1){// checks if its the get color tool selected or not
		if (Fl::event_button() == 1){ // left mouse event for setting left color
			if (drawToolOn)	// checks if draw is enabled
				{
					if(eventhdlGBL == FL_RELEASE||eventhdlGBL == FL_PUSH){ //  should add on release to save memory a bit
						undoAdd();
					}
					win->getMouse(&win->mouseClick);
					for(int i=0-toolSize;i<toolSize;i++)// draws from -toolSize of click point to + toolSize
					{
						for(int j=0-toolSize; j<toolSize;j++)
						{
							//old spot for undoAdd() it was interesting, it gave each level... of the draw ;)
							myImage.setPixel((int)win->mouseClick.x+i, (int)win->mouseClick.y+j, 0, leftMouseInt.r); 
							myImage.setPixel((int)win->mouseClick.x+i, (int)win->mouseClick.y+j, 1, leftMouseInt.g); 
							myImage.setPixel((int)win->mouseClick.x+i, (int)win->mouseClick.y+j, 2, leftMouseInt.b); 
						}
					}
				}// ends the toolon if
			//std::cout << "Look I left clicked!" << std::endl;
		}
		if (Fl::event_button() == 3){ // left mouse event  for setting right color
			if (drawToolOn)
					{
						if(eventhdlGBL == FL_RELEASE||eventhdlGBL == FL_PUSH){ //  should add on release to save memory a bit
							undoAdd();
						}
						win->getMouse(&win->mouseClick);
						for(int i=0-toolSize;i<toolSize;i++)
						{
							for(int j=0-toolSize; j<toolSize;j++)
							{
								myImage.setPixel((int)win->mouseClick.x+i, (int)win->mouseClick.y+j, 0, rightMouseInt.r); 
								myImage.setPixel((int)win->mouseClick.x+i, (int)win->mouseClick.y+j, 1, rightMouseInt.g); 
								myImage.setPixel((int)win->mouseClick.x+i, (int)win->mouseClick.y+j, 2, rightMouseInt.b); 
								win->redraw();
							}
						}
					}
			//std::cout << "Look I right clicked!" << std::endl;
		}
	}
}

/*
Bellow is the code for the basic line tool it sort of does stuff and will throw div 0 errors..
//find m
//find b
for(x=mouseClick.x;x<mousePosition.x;x++){
	setPixel(x,m*x+b,0); // use color values from left or right click of mouse
	setPixel(x,m*x+b,1);
	setPixel(x,m*x+b,2);
}

}

*/

float m=0;

void lineTool(){
	if(tool == 3){// checks if its the get color tool selected or not
		if (Fl::event_button() == 1){ // left mouse event for setting left color
			if (drawToolOn)	// checks if draw is enabled
				{
					if(eventhdlGBL == FL_RELEASE||eventhdlGBL == FL_PUSH){ //  should add on release to save memory a bit
						
						if(eventhdlGBL == FL_PUSH){
							undoAdd();
							win->getMouse(&win->mouseClick);
						}
						if(eventhdlGBL == FL_RELEASE){
							win->getMouse(&win->mousePosition);
						}
					}
					if(eventhdlGBL == FL_DRAG||eventhdlGBL == FL_RELEASE){
							//sets up for the mx + b format... i think this will only draw left to right...
							win->getMouse(&win->mousePosition);
							if((win->mousePosition.x - win->mouseClick.x)==0){
								std::cout<<"Sorry Div Zero in line Tool... sets M =1"<< std::endl;
							}
							else{
								m = (win->mousePosition.y - win->mouseClick.y)/(win->mousePosition.x - win->mouseClick.x); // gets the slope
								std::cout<<"m= " << m << std::endl;
							}
							int b = win->mouseClick.y; //gets the b
							if(eventhdlGBL == FL_RELEASE){
								// there needs to be detection if x<win->mousePosistion.x
								int c;
								if(win->mouseClick.x<win->mousePosition.x){
									c=1;
								}
								if(win->mouseClick.x<win->mousePosition.x){
									c=-1;
								}
								if(win->mouseClick.x==win->mousePosition.x){
									c=win->mousePosition.x;
								}
								if(win->mouseClick.x<=win->mousePosition.x){//if start is less then end do left to right draw of left color
									for(int x = win->mouseClick.x; (x<=win->mousePosition.x); x++){// (x>(int)win->mousePosition.x)&& needs to work for - or + c... for the bounds maybe just do tilll ==
										for(int i=0-toolSize;i<toolSize;i++)// draws from -toolSize of click point to + toolSize
										{
											for(int j=0-toolSize; j<toolSize;j++)
											{
												//old spot for undoAdd() it was interesting, it gave each level... of the draw ;)
												myImage.setPixel(x+i, ((m*x)+b)+j, 0, leftMouseInt.r); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 1, leftMouseInt.g); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 2, leftMouseInt.b); 
											}
										}
									}//ends outer
								}
								else{
									for(int x = win->mouseClick.x; (x>win->mousePosition.x); x--){// (x>(int)win->mousePosition.x)&& needs to work for - or + c... for the bounds maybe just do tilll ==
										for(int i=0-toolSize;i<toolSize;i++)// draws from -toolSize of click point to + toolSize
										{
											for(int j=0-toolSize; j<toolSize;j++)
											{
												//old spot for undoAdd() it was interesting, it gave each level... of the draw ;)
												myImage.setPixel(x+i, ((m*x)+b)+j, 0, leftMouseInt.r); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 1, leftMouseInt.g); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 2, leftMouseInt.b); 
											}
										}
									}//ends outer
								}//end else
							}
					}
				}// ends the toolon if
			//std::cout << "Look I left clicked!" << std::endl;
		}
		if (Fl::event_button() == 3){ // right mouse event  for setting right color
			if (drawToolOn)	// checks if draw is enabled
				{
					if(eventhdlGBL == FL_RELEASE||eventhdlGBL == FL_PUSH){ //  should add on release to save memory a bit
						
						if(eventhdlGBL == FL_PUSH){
							undoAdd();
							win->getMouse(&win->mouseClick);
						}
						if(eventhdlGBL == FL_RELEASE){
							win->getMouse(&win->mousePosition);
						}
					}
					if(eventhdlGBL == FL_DRAG||eventhdlGBL == FL_RELEASE){
							//sets up for the mx + b format... i think this will only draw left to right...
							win->getMouse(&win->mousePosition);
							if((win->mousePosition.x - win->mouseClick.x)==0){
								std::cout<<"Sorry Div Zero in line Tool..."<< std::endl;
							}
							else{
								m = (win->mousePosition.y - win->mouseClick.y)/(win->mousePosition.x - win->mouseClick.x); // gets the slope
								std::cout<<"m= " << m << std::endl;
							}
							int b = win->mouseClick.y; //gets the b
							if(eventhdlGBL == FL_RELEASE){
								// there needs to be detection if x<win->mousePosistion.x
								int c;
								if(win->mouseClick.x<win->mousePosition.x){
									c=1;
								}
								if(win->mouseClick.x<win->mousePosition.x){
									c=-1;
								}
								if(win->mouseClick.x==win->mousePosition.x){
									c=win->mousePosition.x;
								}
								if(win->mouseClick.x<=win->mousePosition.x){//if start is less then end do left to right draw
									for(int x = win->mouseClick.x; (x<=win->mousePosition.x); x++){// (x>(int)win->mousePosition.x)&& needs to work for - or + c... for the bounds maybe just do tilll ==
										for(int i=0-toolSize;i<toolSize;i++)// draws from -toolSize of click point to + toolSize
										{
											for(int j=0-toolSize; j<toolSize;j++)
											{
												//old spot for undoAdd() it was interesting, it gave each level... of the draw ;)
												myImage.setPixel(x+i, ((m*x)+b)+j, 0, rightMouseInt.r); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 1, rightMouseInt.g); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 2, rightMouseInt.b); 
												win->redraw();
											}
										}
									}//ends outer
								}
								else{
									for(int x = win->mouseClick.x; (x>win->mousePosition.x); x--){// (x>(int)win->mousePosition.x)&& needs to work for - or + c... for the bounds maybe just do tilll ==
										for(int i=0-toolSize;i<toolSize;i++)// draws from -toolSize of click point to + toolSize
										{
											for(int j=0-toolSize; j<toolSize;j++)
											{
												//old spot for undoAdd() it was interesting, it gave each level... of the draw ;)
												myImage.setPixel(x+i, ((m*x)+b)+j, 0, rightMouseInt.r); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 1, rightMouseInt.g); 
												myImage.setPixel(x+i, ((m*x)+b)+j, 2, rightMouseInt.b); 
												win->redraw();
											}
										}
									}//ends outer
								}//end else
							}
					}
				}// ends the toolon if
			//std::cout << "Look I left clicked!" << std::endl;
		
		}
	}//end of tool check
}//end of line tool code


void getColorTool(){
	if(tool == 2){// checks if its the get color tool selected or not
		if (Fl::event_button() == 1){ // left mouse event for setting left color
			getColorLeft(); //sets the color of the leftClick thinger (its a global) So dont worry               
			//std::cout << "Set the Left click values...." << std::endl;
		}
		if (Fl::event_button() == 3){ // left mouse event  for setting right color
			getColorRight(); // sets the color of the rightclick thinger.....
			//std::cout << "Set the Right click values...." << std::endl;
		}
	}
	//if its not the tool, don't do anything
}

void replaceColorTool(){
	if(tool == 4){// checks if its the get color tool selected or not
		if (Fl::event_button() == 1){ // left mouse event for setting left color to replace with
			getColorLeft(); //sets the color of the leftClick thinger (its a global) So dont worry               
			
		}
		if (Fl::event_button() == 3){ // left mouse event  for setting right color to be replaced
			getColorRight(); // sets the color of the rightclick thinger.....
			undoAdd();
			replaceColor();
			//std::cout << "Set the Right click values...." << std::endl;
		}
	}
	//if its not the tool, don't do anything
}

void replaceColor(){
	for(int y=0; y<myImage.ny; y++) {
                        for(int x=0; x<myImage.nx; x++) {
								
								int cr=0;//intializes current red to 0
								int cg=0;//initiallizes current green to 0
								int cb=0;//initializes current blue to 0

								cr = myImage.getPixel(x,y,0);//gets the current pixelvalue red sets it to cr
								cg = myImage.getPixel(x,y,1);//gets the current pixelvalue green sets it to cg
								cb = myImage.getPixel(x,y,2);//gets the current pixelvalue blue sets it to cb
								if ((rightMouseInt.r == cr) && (rightMouseInt.g == cg) && (rightMouseInt.b == cb)){
									myImage.setPixel(x,y,0,leftMouseInt.r);
									myImage.setPixel(x,y,1,leftMouseInt.g);
									myImage.setPixel(x,y,2,leftMouseInt.b);
								}
						
                        }
        }
}

void toHex(){
	std::cout << std::hex;
	//char*temp = new char [size];
        /*for (int i=2*sizeof(int) - 1; i>=0; i--) {
			std::cout << "0123456789ABCDEF"[(((int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 0)) >> i*4) & 0xF)];
        }*/
		//std::cout << std::endl;
		//number = temp;
		//return temp;
		//std::cout << std::hex << (int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 0));
		//std::cout << std::hex << (int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 1));
		//std::cout << std::hex << (int)(myImage.getPixel(win->mouseClick.x, win->mouseClick.y, 2));
		//std::cout << std::endl;
}

void toDec(){
	std::cout << std::dec;
}


Image& Image::operator=(const Image& rhs){

			if (this != &rhs){
			this->nx = rhs.nx;
			this->ny = rhs.ny;
			this->ncolorChannels = rhs.ncolorChannels;

						
		  }
			  return *this;
	  }